<template>
  <view class="x-preview">
    <view v-if="! props.title" class="title">{{ props.title }}</view>
    <view v-if="props.mode == 'grid'" class="grid">
      <view :key="index" v-for="(file, index) in fileList" :style="{width: props.size + 'rpx', height: props.size + 'rpx'}"
            class="image-box">
        <image class="icon" v-if="! props.disabled" @click="onRemove(file, index)" :src="`${publicPath}del.png`" />
        <image :style="{width: (props.size - 11) + 'rpx', height: (props.size - 11) + 'rpx'}"
               v-if="['png', 'jpg', 'jpeg'].indexOf(file.ext) > -1" @click="onPreview(file)" class="source"
               :src="file.url"></image>
        <image :style="{width: (props.size - 11) + 'rpx', height: (props.size - 11) + 'rpx'}" @click="onPreview(file)"
               class="source" v-else :src="`${publicPath}${getIcon(file.ext)}`"></image>
      </view>
      <slot name="suffix"></slot>
    </view>

    <view class="list" v-if="props.mode == 'list'">
      <view class="file-box" v-for="(file, index) in fileList" :key="index">
        <view class="info">
          <image class="icon" :src="`${publicPath}${getIcon(file.ext)}`"></image>
          <view class="text" @click="onPreview(file)">{{file.name || props.defaultName || file.uid}}</view>
        </view>
        <image v-if="! props.disabled" class="icon" @click="onRemove(file, index)" :src="`${publicPath}del.png`" />
      </view>
    </view>

    <view v-if="props.mode == 'custom'">
      <view @click="onPreview(file)" v-for="(file, index) in fileList">
        <slot name="text" :data="file"></slot>
      </view>
    </view>
  </view>
</template>

<script setup>
import {Http, Helper, Msg} from "core";

import {ref, toRaw, watch} from "vue";
import {GlobalConfig} from 'core';
const {appConfig} = GlobalConfig();
let httpConfig = appConfig.http;
// const publicPath = import.meta.env.VITE_SERVER_URL + '/image/'

const props = defineProps({
  list: {
    type: Array,
    default: () => {
      return []
    }
  },

  title: {
    type: String,
    default: ''
  },

  size: {
    type: String,
    default: '145',
  },

  disabled: {
    type: Boolean,
    default: true,
  },

  mode: {
    type: String,
    default: 'list'
  },

  isPreview: {
    type: Boolean,
    default: true
  },

  defaultName: {
    type: String,
    default: "",
  },
})

const fileList = ref([])

const handlerValue = (files)=> {
  let list = [];
  if (!Helper.emptyArray(files)) {
    Msg.loading("下载中...");
    setTimeout(() => {
      Msg.loading(false)
    }, 20000)

    for (let i = 0; i < files.length; i++) {
      let path = files[i];
      let file = {};

      if(! validUrl(path)) {
        file.url = httpConfig.downloadUrl + path;
      }

      file.name = getFileNameByUrl(path)
      let ext = "";
      if (file.name) {
        ext = file.name.substr(file.name.lastIndexOf(".") + 1);
      }

      file.ext = ext;
      list.push(file);
    }
    Msg.loading(false)
    fileList.value = list;
  }
}

const validUrl = (url)=> {
  return !(url.indexOf("wxfile") == -1 && url.indexOf("http") == -1 && url.indexOf("https") == -1)
}

const emit = defineEmits([
    'success',
    'preview',
    'remove'
])

const onPreview = async (file)=> {
  let isBase64 = file.isBase64;
  if (isBase64) {
    previewBase64(file.url, file.ext);
    emit("preview", file.url)
    return;
  }

  openFile(file.url, file.ext);
  emit("preview", file.url)
}

const previewBase64 = (base64, fileType, os = 'WX')=> {
  // 这是我自定义的文件名，小程序打开后转发或者收藏就是这个名字
  let filePath = '';
  // #ifdef MP-ALIPAY
    filePath = wx.env.USER_DATA_PATH + '/' + new Date().getTime() + '.' + fileType;
  // #endif
  // #ifdef MP-ALIPAY
    filePath = my.env.USER_DATA_PATH + '/' + new Date().getTime() + '.' + fileType;
  // #endif

  //把base64数据转buffer，wx.base64ToArrayBuffer此功能官方不再维护 但是可以正常使用
  // let base64buffer = uni.arrayBufferToBase64(base64);
  // 使用微信文件管理器 将buffer数据写入文件
  uni.getFileSystemManager().writeFile({
    filePath: filePath,
    data: base64,
    encoding: 'base64', // 指定二进制格式
    success: res => {
      // 打开文件
      openFile(filePath, fileType)
    },
    fail: res => {
      console.error('写入文件失败：', res)
    }
  })
}

const openFile = (url, ext)=> {

  if (['png', 'jpg', 'jpeg'].indexOf(ext) > -1) {
    uni.previewImage({
      urls: [url],
      loop: true,
      // success: (res)=>{
      //
      // },
      fail: (error) => {
        //todo 上报日志
        Msg.error("打开文件失败");
      }
    })
    return;
  }

  let fileType = ['doc', 'xlsx', 'pptx', 'xls', 'ppt', 'pdf', 'docx'];
  if (fileType.indexOf(ext) > -1) {
    uni.openDocument({
      filePath: url,
      fileType: ext,
      fail: (error) => {
        console.log(error)
        //todo 上报日志
        Msg.error("打开文件失败");
      }
    })
  }
}

const onRemove = (file, index)=> {
  Msg.confirm( "是否删除该附件").then(data => {
    if (index > -1) {
      fileList.value.splice(index, 1)
      emit("remove", index, file, fileList.value);
    }
  })
}

const getIcon = (ext)=> {
  if (ext == 'pdf') {
    return 'pdf.png';
  }

  if (['doc', 'docx'].indexOf(ext) > -1) {
    return 'word.png';
  }

  if (['xls', 'xlsx', 'xlsm'].indexOf(ext) > -1) {
    return 'excel.png'
  }

  return "file.png";
}

const getFileNameByUrl = (file) => {
  let fileName = "";
  if(file.indexOf("?") > -1) {
    let suffix = file.split("?")[1];
    if(! Helper.empty(suffix)) {
      let paramArr = suffix.split("&");
      for (let i=0;i<paramArr.length;i++) {
        let item = paramArr[i].split("=");
        let key = item[0];
        if((key == 'name' || key == 'fileName') && item.length == 2) {
          fileName = item[1];
          break
        }
      }
    }
  }

  if(Helper.empty(fileName)) {
    fileName = file.substring(file.lastIndexOf("/") + 1);
  }

  return fileName;
}

watch(()=> props.list, (value)=>{
  if (Helper.emptyArray(value)) {
    value = [];
  }

  handlerValue(value);
}, {deep: true, immediate: true})

</script>

<style lang="less" scoped>
.x-preview {
  width: 100%;
  background-color: #fff;
  padding: 0 20rpx;
  box-sizing: border-box;
  position: static;

  .title {
    // padding: 22rpx 0;
    box-sizing: border-box;
  }

  .grid {
    display: flex;
    flex-direction: row;
    align-items: center;

    .image-box {
      position: relative;
      margin-right: 20rpx;
      margin-bottom: 20rpx;
      border: 1rpx solid #eaeaea;

      .icon {
        position: absolute;
        right: -8rpx;
        top: -8rpx;
        z-index: 99;
        width: 44rpx;
        height: 44rpx;
      }

      .source {
        position: absolute;
        top: 8rpx;
        left: 8rpx;
      }
    }
  }

  .list {
    display: flex;
    flex-direction: column;

    .file-box {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding-bottom: 10rpx;
      box-sizing: border-box;

      .info {
        display: flex;
        flex-direction: row;
        align-items: center;

        .text {
          width: 500rpx;
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
          margin-left: 10rpx;
        }

        .text:first-child {
          font-weight: 600;
        }

        .text:last-child {
          margin-top: 10rpx;
          font-size: 30rpx;
          color: #999999;
        }

        .icon {
          width: 44rpx;
          height: 44rpx;
        }
      }

      .icon {
        width: 40rpx;
        height: 40rpx;
      }
    }
  }
}
</style>
